#include "zlang.h"

#define ZLANG_OBJECT_bmp	"bmp"

#include "libbmp.h"

struct ZlangDirectProperty_bmp
{
	struct BitmapContext	*ctx ;
} ;

static void FreeBitmapContextIfCreated( struct ZlangDirectProperty_bmp *bmp_direct_prop )
{
	if( bmp_direct_prop->ctx )
	{
		FreeBitmapContext( bmp_direct_prop->ctx );
		bmp_direct_prop->ctx = NULL ;
	}
	
	return;
}

ZlangInvokeFunction ZlangInvokeFunction_bmp_GetLastErrno;
int ZlangInvokeFunction_bmp_GetLastErrno( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_bmp	*bmp_direct_prop = GetObjectDirectProperty(obj) ;
	struct ZlangObject		*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	int32_t				errno ;
	
	errno = GetBitmapLastError( bmp_direct_prop->ctx ) ;
	
	CallRuntimeFunction_int_SetIntValue( rt , out1 , errno );
	return 0;
}

ZlangInvokeFunction ZlangInvokeFunction_bmp_CreateImage_int_int_int_int_int_int_int_int;
int ZlangInvokeFunction_bmp_CreateImage_int_int_int_int_int_int_int_int( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_bmp	*bmp_direct_prop = GetObjectDirectProperty(obj) ;
	struct ZlangObject		*in1 = GetInputParameterInLocalObjectStack(rt,1) ;
	struct ZlangObject		*in2 = GetInputParameterInLocalObjectStack(rt,2) ;
	struct ZlangObject		*in3 = GetInputParameterInLocalObjectStack(rt,3) ;
	struct ZlangObject		*in4 = GetInputParameterInLocalObjectStack(rt,4) ;
	struct ZlangObject		*in5 = GetInputParameterInLocalObjectStack(rt,5) ;
	struct ZlangObject		*in6 = GetInputParameterInLocalObjectStack(rt,6) ;
	struct ZlangObject		*in7 = GetInputParameterInLocalObjectStack(rt,7) ;
	struct ZlangObject		*in8 = GetInputParameterInLocalObjectStack(rt,8) ;
	struct ZlangObject		*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	int32_t				width ;
	int32_t				height ;
	int32_t				planes ;
	int32_t				bit_count ;
	int32_t				compression ;
	int32_t				x_pels_per_meter ;
	int32_t				y_pels_per_meter ;
	int32_t				clr_idx ;
	
	CallRuntimeFunction_int_GetIntValue( rt , in1 , & width );
	CallRuntimeFunction_int_GetIntValue( rt , in2 , & height );
	CallRuntimeFunction_int_GetIntValue( rt , in3 , & planes );
	CallRuntimeFunction_int_GetIntValue( rt , in4 , & bit_count );
	CallRuntimeFunction_int_GetIntValue( rt , in5 , & compression );
	CallRuntimeFunction_int_GetIntValue( rt , in6 , & x_pels_per_meter );
	CallRuntimeFunction_int_GetIntValue( rt , in7 , & y_pels_per_meter );
	CallRuntimeFunction_int_GetIntValue( rt , in8 , & clr_idx );
	
	bmp_direct_prop->ctx = CreateBitmapContext( (INT32)width , (INT32)height , (UINT16)planes , (UINT16)bit_count , (UINT32)compression , (INT32)x_pels_per_meter , (INT32)y_pels_per_meter , (UINT8)clr_idx , NULL ) ;
	if( bmp_direct_prop->ctx == NULL )
	{
		CallRuntimeFunction_bool_SetBoolValue( rt , out1 , FALSE );
		return 0;
	}
	
	CallRuntimeFunction_bool_SetBoolValue( rt , out1 , TRUE );
	return 0;
}

ZlangInvokeFunction ZlangInvokeFunction_bmp_LoadFile;
int ZlangInvokeFunction_bmp_LoadFile( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_bmp	*bmp_direct_prop = GetObjectDirectProperty(obj) ;
	struct ZlangObject		*in1 = GetInputParameterInLocalObjectStack(rt,1) ;
	struct ZlangObject		*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	char				*bmp_pathfilename = NULL ;
	struct BitmapContext		*ctx = NULL ;
	
	CallRuntimeFunction_string_GetStringValue( rt , in1 , & bmp_pathfilename , NULL );
	
	ctx = ReadBitmapFile( bmp_pathfilename ) ;
	if( ctx == NULL )
	{
		CallRuntimeFunction_bool_SetBoolValue( rt , out1 , FALSE );
		return 0;
	}
	
	FreeBitmapContextIfCreated( bmp_direct_prop );
	bmp_direct_prop->ctx = ctx ;
	
	CallRuntimeFunction_bool_SetBoolValue( rt , out1 , TRUE );
	return 0;
}

ZlangInvokeFunction ZlangInvokeFunction_bmp_SaveFile;
int ZlangInvokeFunction_bmp_SaveFile( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_bmp	*bmp_direct_prop = GetObjectDirectProperty(obj) ;
	struct ZlangObject		*in1 = GetInputParameterInLocalObjectStack(rt,1) ;
	struct ZlangObject		*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	char				*bmp_pathfilename = NULL ;
	int				nret = 0 ;
	
	CallRuntimeFunction_string_GetStringValue( rt , in1 , & bmp_pathfilename , NULL );
	
	nret = WriteBitmapFile( bmp_direct_prop->ctx , bmp_pathfilename ) ;
	if( nret )
	{
		CallRuntimeFunction_bool_SetBoolValue( rt , out1 , FALSE );
		return 0;
	}
	
	CallRuntimeFunction_bool_SetBoolValue( rt , out1 , TRUE );
	return 0;
}

ZlangInvokeFunction ZlangInvokeFunction_bmp_GetWidth;
int ZlangInvokeFunction_bmp_GetWidth( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_bmp	*bmp_direct_prop = GetObjectDirectProperty(obj) ;
	struct ZlangObject		*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	int32_t				width ;
	
	width = GetBitmapWidth( bmp_direct_prop->ctx ) ;
	
	CallRuntimeFunction_int_SetIntValue( rt , out1 , width );
	return 0;
}

ZlangInvokeFunction ZlangInvokeFunction_bmp_GetHeight;
int ZlangInvokeFunction_bmp_GetHeight( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_bmp	*bmp_direct_prop = GetObjectDirectProperty(obj) ;
	struct ZlangObject		*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	int32_t				height ;
	
	height = GetBitmapHeight( bmp_direct_prop->ctx ) ;
	
	CallRuntimeFunction_int_SetIntValue( rt , out1 , height );
	return 0;
}

ZlangInvokeFunction ZlangInvokeFunction_bmp_GetRgbaInPosition_int_int_int_int_int_int;
int ZlangInvokeFunction_bmp_GetRgbaInPosition_int_int_int_int_int_int( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_bmp	*bmp_direct_prop = GetObjectDirectProperty(obj) ;
	struct ZlangObject		*in1 = GetInputParameterInLocalObjectStack(rt,1) ;
	struct ZlangObject		*in2 = GetInputParameterInLocalObjectStack(rt,2) ;
	struct ZlangObject		*in3 = GetInputParameterInLocalObjectStack(rt,3) ;
	struct ZlangObject		*in4 = GetInputParameterInLocalObjectStack(rt,4) ;
	struct ZlangObject		*in5 = GetInputParameterInLocalObjectStack(rt,5) ;
	struct ZlangObject		*in6 = GetInputParameterInLocalObjectStack(rt,6) ;
	struct ZlangObject		*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	int32_t				width ;
	int32_t				height ;
	struct RBGA			*rgba = NULL ;
	int32_t				red ;
	int32_t				green ;
	int32_t				blue ;
	int32_t				alpha ;
	
	CallRuntimeFunction_int_GetIntValue( rt , in1 , & width );
	CallRuntimeFunction_int_GetIntValue( rt , in2 , & height );
	
	rgba = GetBitmapMatrixRbgaPtr( bmp_direct_prop->ctx , (INT32)width , (INT32)height ) ;
	if( rgba == NULL )
	{
		CallRuntimeFunction_bool_SetBoolValue( rt , out1 , FALSE );
		return 0;
	}
	
	red = rgba->red ;
	green = rgba->green ;
	blue = rgba->blue ;
	alpha = rgba->alpha ;
	CallRuntimeFunction_int_SetIntValue( rt , in3 , red );
	CallRuntimeFunction_int_SetIntValue( rt , in4 , green );
	CallRuntimeFunction_int_SetIntValue( rt , in5 , blue );
	CallRuntimeFunction_int_SetIntValue( rt , in6 , alpha );
	
	CallRuntimeFunction_bool_SetBoolValue( rt , out1 , TRUE );
	return 0;
}

ZlangInvokeFunction ZlangInvokeFunction_bmp_SetRgbaInPosition_int_int_int_int_int_int;
int ZlangInvokeFunction_bmp_SetRgbaInPosition_int_int_int_int_int_int( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_bmp	*bmp_direct_prop = GetObjectDirectProperty(obj) ;
	struct ZlangObject		*in1 = GetInputParameterInLocalObjectStack(rt,1) ;
	struct ZlangObject		*in2 = GetInputParameterInLocalObjectStack(rt,2) ;
	struct ZlangObject		*in3 = GetInputParameterInLocalObjectStack(rt,3) ;
	struct ZlangObject		*in4 = GetInputParameterInLocalObjectStack(rt,4) ;
	struct ZlangObject		*in5 = GetInputParameterInLocalObjectStack(rt,5) ;
	struct ZlangObject		*in6 = GetInputParameterInLocalObjectStack(rt,6) ;
	struct ZlangObject		*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	int32_t				width ;
	int32_t				height ;
	int32_t				red ;
	int32_t				green ;
	int32_t				blue ;
	int32_t				alpha ;
	struct RBGA			rgba ;
	int				nret = 0 ;
	
	CallRuntimeFunction_int_GetIntValue( rt , in1 , & width );
	CallRuntimeFunction_int_GetIntValue( rt , in2 , & height );
	CallRuntimeFunction_int_GetIntValue( rt , in3 , & red );
	CallRuntimeFunction_int_GetIntValue( rt , in4 , & green );
	CallRuntimeFunction_int_GetIntValue( rt , in5 , & blue );
	CallRuntimeFunction_int_GetIntValue( rt , in6 , & alpha );
	
	rgba.red = red ;
	rgba.green = green ;
	rgba.blue = blue ;
	rgba.alpha = alpha ;
	nret = SetBitmapMatrixRbga( bmp_direct_prop->ctx , (INT32)width , (INT32)height , & rgba ) ;
	if( nret )
	{
		CallRuntimeFunction_bool_SetBoolValue( rt , out1 , FALSE );
		return 0;
	}
	
	CallRuntimeFunction_bool_SetBoolValue( rt , out1 , TRUE );
	return 0;
}

ZlangCreateDirectPropertyFunction ZlangCreateDirectProperty_bmp;
void *ZlangCreateDirectProperty_bmp( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_bmp	*bmp_prop = NULL ;
	
	bmp_prop = (struct ZlangDirectProperty_bmp *)malloc( sizeof(struct ZlangDirectProperty_bmp) ) ;
	if( bmp_prop == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for entity" )
		return NULL;
	}
	memset( bmp_prop , 0x00 , sizeof(struct ZlangDirectProperty_bmp) );
	
	return bmp_prop;
}

ZlangDestroyDirectPropertyFunction ZlangDestroyDirectProperty_bmp;
void ZlangDestroyDirectProperty_bmp( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_bmp	*bmp_direct_prop = GetObjectDirectProperty(obj) ;
	
	FreeBitmapContextIfCreated( bmp_direct_prop );
	
	free( bmp_direct_prop );
	
	return;
}

static struct ZlangDirectFunctions direct_funcs_bmp =
	{
		ZLANG_OBJECT_bmp , /* char *ancestor_name */
		
		ZlangCreateDirectProperty_bmp , /* ZlangCreateDirectPropertyFunction *create_entity_func */
		ZlangDestroyDirectProperty_bmp , /* ZlangDestroyDirectPropertyFunction *destroy_entity_func */
		
		NULL , /* ZlangFromCharPtrFunction *from_char_ptr_func */
		NULL , /* ZlangToStringFunction *to_string_func */
		NULL , /* ZlangFromDataPtrFunction *from_data_ptr_func */
		NULL , /* ZlangGetDataPtrFunction *get_data_ptr_func */
		
		NULL , /* ZlangOperatorFunction *oper_PLUS_func */
		NULL , /* ZlangOperatorFunction *oper_MINUS_func */
		NULL , /* ZlangOperatorFunction *oper_MUL_func */
		NULL , /* ZlangOperatorFunction *oper_DIV_func */
		NULL , /* ZlangOperatorFunction *oper_MOD_func */
		
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_NEGATIVE_func */
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_NOT_func */
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_BIT_REVERSE_func */
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_PLUS_PLUS_func */
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_MINUS_MINUS_func */
		
		NULL , /* ZlangCompareFunction *comp_EGUAL_func */
		NULL , /* ZlangCompareFunction *comp_NOTEGUAL_func */
		NULL , /* ZlangCompareFunction *comp_LT_func */
		NULL , /* ZlangCompareFunction *comp_LE_func */
		NULL , /* ZlangCompareFunction *comp_GT_func */
		NULL , /* ZlangCompareFunction *comp_GE_func */
		
		NULL , /* ZlangLogicFunction *logic_AND_func */
		NULL , /* ZlangLogicFunction *logic_OR_func */
		
		NULL , /* ZlangLogicFunction *bit_AND_func */
		NULL , /* ZlangLogicFunction *bit_XOR_func */
		NULL , /* ZlangLogicFunction *bit_OR_func */
		NULL , /* ZlangLogicFunction *bit_MOVELEFT_func */
		NULL , /* ZlangLogicFunction *bit_MOVERIGHT_func */
	} ;

ZlangImportObjectsFunction ZlangImportObjects;
int ZlangImportObjects( struct ZlangRuntime *rt )
{
	struct ZlangObject	*obj = NULL ;
	struct ZlangFunction	*func = NULL ;
	int			nret = 0 ;
	
	nret = ImportObject( rt , & obj , ZLANG_OBJECT_bmp , & direct_funcs_bmp , sizeof(struct ZlangDirectFunctions) , NULL ) ;
	if( nret )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_LINK_FUNC_TO_ENTITY , "import object to global objects heap" )
		return GetRuntimeErrorNo(rt);
	}
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_bmp_GetLastErrno , ZLANG_OBJECT_int , "GetLastErrno" , NULL ) ;
	if( func == NULL )
		return GetRuntimeErrorNo(rt);
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_bmp_CreateImage_int_int_int_int_int_int_int_int , ZLANG_OBJECT_bool , "CreateImage" , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_int,NULL , NULL ) ;
	if( func == NULL )
		return GetRuntimeErrorNo(rt);
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_bmp_LoadFile , ZLANG_OBJECT_bool , "LoadFile" , ZLANG_OBJECT_string,NULL , NULL ) ;
	if( func == NULL )
		return GetRuntimeErrorNo(rt);
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_bmp_SaveFile , ZLANG_OBJECT_bool , "SaveFile" , ZLANG_OBJECT_string,NULL , NULL ) ;
	if( func == NULL )
		return GetRuntimeErrorNo(rt);
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_bmp_GetWidth , ZLANG_OBJECT_int , "GetWidth" , NULL ) ;
	if( func == NULL )
		return GetRuntimeErrorNo(rt);
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_bmp_GetHeight , ZLANG_OBJECT_int , "GetHeight" , NULL ) ;
	if( func == NULL )
		return GetRuntimeErrorNo(rt);
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_bmp_GetRgbaInPosition_int_int_int_int_int_int , ZLANG_OBJECT_bool , "GetRgbaInPosition" , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_int,NULL , NULL ) ;
	if( func == NULL )
		return GetRuntimeErrorNo(rt);
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_bmp_SetRgbaInPosition_int_int_int_int_int_int , ZLANG_OBJECT_bool , "SetRgbaInPosition" , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_int,NULL , ZLANG_OBJECT_int,NULL , NULL ) ;
	if( func == NULL )
		return GetRuntimeErrorNo(rt);
	
	return 0 ;
}

